﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using IntoNails.Infrastructure.DataAccess;
using IntoNails.Infrastructure.Extensions;
using IntoNails.Models;

namespace IntoNails.DataAccess
{
    public class TicketRepository : AbstractDataRepository<Ticket, Guid>, IDataFileRepository, ITicketRepository
    {
        public TicketRepository(string dataFilePath)
        {
            this.DataFilePath = dataFilePath;
        }

        #region Implementation of IDataFileRepository

        public string DataFilePath { get; set; }

        #endregion

        #region Overriden

        public override Ticket Get(Guid uniqueCode)
        {
            return this.InnerDataList.SingleOrDefault(u => u.UniqueCode == uniqueCode);
        }

        public override IEnumerable<Ticket> Get(Func<Ticket, bool> predicate)
        {
            return this.InnerDataList.Where(predicate);
        }

        public override IList<Ticket> GetRawItemList()
        {
            return this.InnerDataList;
        }

        public override void Add(Ticket item)
        {
            if (null == item)
            {
                this.OnDataAdded(new DataEventArgs<Ticket>(new ArgumentNullException("item")));
            }
            else if (this.InnerDataList.Contains(item))
            {
                this.OnDataAdded(new DataEventArgs<Ticket>(false));
            }
            else
            {
                this.InnerDataList.Add(item);
                this.OnDataAdded(new DataEventArgs<Ticket>(true));
            }
        }

        public override void Remove(Guid uniqueCode)
        {
            Ticket aboutToRemoveTicket = this.Get(uniqueCode);
            if (null == aboutToRemoveTicket)
            {
                this.OnDataRemoved(new DataEventArgs<Ticket>(new NullReferenceException("aboutToRemoveTicket")));
            }
            else
            {
                this.InnerDataList.Remove(aboutToRemoveTicket);
                this.OnDataRemoved(new DataEventArgs<Ticket>(true));
            }
        }

        public override void Update(Guid oldItemKey, Ticket newItem)
        {
            throw new NotImplementedException();
        }

        public override void Save()
        {
            using (Stream saveDataStream = new FileStream(this.DataFilePath, FileMode.OpenOrCreate, FileAccess.Write))
            {
                this.InnerDataList.Serialize(saveDataStream);
            }
        }

        public override int Load()
        {
            if (!File.Exists(this.DataFilePath))
            {
                this.InnerDataList = new List<Ticket>();
            }
            else
            {
                using (Stream loadDataStream = new FileStream(this.DataFilePath, FileMode.Open, FileAccess.Read))
                {
                    this.InnerDataList = loadDataStream.Deserialize<List<Ticket>>();
                }
            }

            return this.InnerDataList.Count;
        }

        public override void Initialize()
        {
            base.InnerDataList = new List<Ticket>();
        }
        
        #endregion
    }
}
